package com.dong.ch03_stack_queue;

import lombok.extern.slf4j.Slf4j;

/**
 * 给你一份工作时间表 hours，上面记录着某一位员工每天的工作小时数。
 *
 * 我们认为当员工一天中的工作小时数大于 8 小时的时候，那么这一天就是「劳累的一天」。
 *
 * 所谓「表现良好的时间段」，意味在这段时间内，「劳累的天数」是严格 大于「不劳累的天数」。
 *
 * 请你返回「表现良好时间段」的最大长度。
 *
 *  
 *
 * 示例 1：
 *
 * 输入：hours = [9,9,6,0,6,6,9]
 * 输出：3
 * 解释：最长的表现良好时间段是 [9,9,6]。
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/longest-well-performing-interval
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
@Slf4j
public class Solution1124 {
    public static void main(String[] args) {
        Solution1124 s = new Solution1124();
          int[] hours = new int[]{9,9,6,0,6,6,9};
        //  int[] hours = new int[]{4,11,3,4};
        //   int[] hours = new int[]{6,9,9};
        System.out.println(s.longestWPI(hours));
    }
    public int longestWPI(int[] hours) {
        int maxTotalBusyDays = 0;
        int totalTiredDays = 0;
        int leftIndex = 0;
        int rightIndex = 1;
        if(isBusyDay(hours,leftIndex)) {
            totalTiredDays=getTotalBusyGap(hours,0,0);
            if(totalTiredDays>maxTotalBusyDays) {
                maxTotalBusyDays=totalTiredDays;
            }
        }
        boolean breakFlag= false;
        while(leftIndex<hours.length&&!breakFlag) {
   //        log.error("out, left: {},right: {}",leftIndex,rightIndex);
            while(inBusyRange(hours,leftIndex,rightIndex)&&!breakFlag) {
                System.out.println("inner 1");
                totalTiredDays=getTotalBusyGap(hours,leftIndex,rightIndex);
                if(totalTiredDays>maxTotalBusyDays) {
                    maxTotalBusyDays=totalTiredDays;
                }
                rightIndex++;
                if(rightIndex>hours.length-1) {
                    rightIndex=hours.length-1;
                    breakFlag=true;
                }
            }
            //right 进行轮询遍历 ->
            int tmpRight = rightIndex;
            int tmpTotal = totalTiredDays;
            boolean trySuccess=false;
             tmpRight = hours.length-1;
            while(tmpRight>rightIndex) {
  //              log.warn("inner 2, left: {},right: {}",leftIndex,rightIndex);

                if(inBusyRange(hours,leftIndex,tmpRight)) {
                    trySuccess=true;
                    rightIndex=tmpRight;
                    if(rightIndex>hours.length-1) {
                        breakFlag=true;
                        rightIndex=hours.length-1;
                    }
                    tmpTotal=getTotalBusyGap(hours,leftIndex,tmpRight);
                    if(tmpTotal>maxTotalBusyDays) {
                        maxTotalBusyDays=tmpTotal;
                    }
                    break;
                }
                tmpRight =  rightSkip(hours,tmpRight,rightIndex);
            }
            if(!trySuccess) {
                if(isBusyDay(hours,rightIndex)) {
                    if(maxTotalBusyDays==0) {
                        maxTotalBusyDays=1;
                    }
                }
                if(rightIndex<hours.length-2) {
                    rightIndex++;
                }
            }
            //left ->
            leftIndex=leftSkip(hours,leftIndex,rightIndex);
        }
        return maxTotalBusyDays;
    }
    //   <-
    private int rightSkip(int[] arr,int rightIndex,int bound) {
 //       log.info("[ right skip : ], before : {}",rightIndex);
        int tmpRight = rightIndex;
        while(inBusyRange(arr,tmpRight,rightIndex)) {
            tmpRight--;
            if(tmpRight<=bound) {
 //               log.info("[ right skip : ], after 1 : {}",tmpRight);
                return tmpRight;
            }
        }
        int finalRight = tmpRight==rightIndex?rightIndex-1:tmpRight;
  //      log.info("[ right skip : ], after 2 : {}",finalRight);
        return finalRight;
    }
    //   ->
    private int leftSkip(int[] arr, int leftIndex,int bound) {
   //     log.info("[ left skip : ], before : {}",leftIndex);
        int tmpLeft =leftIndex;
        while (inBusyRange(arr,leftIndex,tmpLeft)) {
           tmpLeft++;
           if(tmpLeft>=bound) {
    //           log.info("[ left skip : ], after 1: {}",tmpLeft);
               return tmpLeft;
           }
        }
        int finalLeft = tmpLeft==leftIndex?leftIndex+1:tmpLeft;
   //     log.info("[ left skip : ], after 2: {}",finalLeft);
        return  finalLeft;
    }

    /**
     * 必须在busyRange这个方法才有效
     * @param arr
     * @param left
     * @param right
     * @return
     */
    private int getTotalBusyGap(int[] arr, int left , int right) {
        if(right>arr.length-1) {
            right=arr.length-1;
        }
        int gap=right-left+1;
        return gap;
    }

    private boolean inBusyRange(int[]arr , int left, int right) {
        return getTotalBusyDayBigger8(arr, left, right) * 2 > (right - left + 1);
    }
    private boolean isBusyDay(int[] arr ,int index) {
        return arr[index]>8;
    }
    //可以使用线段树做缓存
    private int getTotalBusyDayBigger8(int[]arr, int left, int right) {
        int total=0;
        for (int i = left ;i<=right;i++) {
            if (isBusyDay(arr,i)) {
                total++;
            }
        }
        return total;
    }
}
